library(Seurat)
library(ggplot2)
library(cowplot)
library(dplyr)
library(devtools)
SLICE_3 <- Load10X_Spatial(data.dir = "/local1/DATA/sequencing/20200225_P1168_ASHLEY_10X_VISIUM_Lineage_Tracing_Visium_d15/processed/manual_alignments/SLICE_3/outs/", slice = "SLICE_3", filter.matrix = TRUE)

sctransfrom to normalize the data and detect high-variance features

SLICE_3 <- SCTransform(SLICE_3, assay = "Spatial", verbose = FALSE)

write table with raw data counts

write.table(SLICE_3@assays$SCT@counts, file = "~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/rawdataSLICE3_SCT.txt", quote = FALSE, sep = "\t")
write.table(SLICE_3@assays$Spatial@counts, file = "~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/rawdataSLICE3_Spatial.txt", quote = FALSE, sep = "\t")

SCT_cibsortx_input <- read.table("~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/rawdataSLICE3_SCT.txt", row.names = NULL, sep = "\t")
head(SCT_cibsortx_input)
names(SCT_cibsortx_input)[names(SCT_cibsortx_input) == "row.names"] <- "genes"
head(SCT_cibsortx_input)
write.table(SCT_cibsortx_input, file = "~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/SCT_cibsortx_input_SLICE_3.txt", quote = FALSE, sep = "\t", row.names=F)

Spatial_cibsortx_input <- read.table("~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/rawdataSLICE3_Spatial.txt", row.names = NULL, sep = "\t")
head(Spatial_cibsortx_input)
names(Spatial_cibsortx_input)[names(Spatial_cibsortx_input) == "row.names"] <- "genes"
head(Spatial_cibsortx_input)
write.table(Spatial_cibsortx_input, file = "~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/Spatial_cibsortx_input_SLICE_3.txt", quote = FALSE, sep = "\t", row.names=F)

interactive plot to identify spots not connected to tissue

ISpatialDimPlot(SLICE_3, image = NULL, alpha = c(0.3, 1))

Filter out spots with less than 1000 feature and not connected to tissue

# hist(SLICE_3$nFeature_Spatial)
# low_feature_cut <- 1000
# WhichCells(SLICE_3, expression = nFeature_Spatial < low_feature_cut)
# SpatialDimPlot(SLICE_3, cells.highlight = WhichCells(SLICE_3, expression = nFeature_Spatial < low_feature_cut))
# SpatialFeaturePlot(SLICE_3, features = 'nFeature_SCT')

# cells_drop <- WhichCells(SLICE_3, expression = nFeature_Spatial < low_feature_cut)
# all_cells_todrop <- rownames(SLICE_3@meta.data)[which(rownames(SLICE_3@meta.data) %in% c(cells_drop))] #all spots are touching tissue (this slice is manually tissue annotated upstream in loupe browser)
# 
# png("~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/Dimplot_cellstodrop.png", width = 10, height = 10, units = "in", res = 300)
# SpatialDimPlot(SLICE_3, cells.highlight = all_cells_todrop, pt.size.factor = 2, stroke = .5)
# dev.off()
# 
# cells_to_keep <- rownames(SLICE_3@meta.data)[!rownames(SLICE_3@meta.data) %in% all_cells_todrop]
# 
# SLICE_3_sub <- subset(SLICE_3, cells = cells_to_keep)
SLICE_3 <- FindVariableFeatures(SLICE_3, selection.method = "vst", nfeatures = 2000)

Dimensionality reduction, clustering, and visualization

Find

dims = 1:9
SLICE_3 <- FindNeighbors(SLICE_3, reduction = "pca", dims = dims)
Computing nearest neighbor graph
Computing SNN

Find best resolution for clustering

Find clusters and run UMAP

res <- 0.5
SLICE_3 <- FindClusters(SLICE_3, verbose = FALSE, resolution = res)
SLICE_3 <- RunUMAP(SLICE_3, reduction = "pca", dims = dims)
09:50:08 UMAP embedding parameters a = 0.9922 b = 1.112
09:50:08 Read 587 rows and found 9 numeric columns
09:50:08 Using Annoy for neighbor search, n_neighbors = 30
09:50:08 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:50:09 Writing NN index file to temp file /tmp/RtmpmdRg7b/file1582d4c8daa07
09:50:09 Searching Annoy index using 1 thread, search_k = 3000
09:50:09 Annoy recall = 100%
09:50:09 Commencing smooth kNN distance calibration using 1 thread
09:50:10 Initializing from normalized Laplacian + noise
09:50:10 Commencing optimization for 500 epochs, with 21068 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:50:13 Optimization finished

plot clusters

plot nfeatures and ncounts

plot3 <- VlnPlot(SLICE_3, features = "nCount_SCT", pt.size = 0.1) + NoLegend()
plot4 <- SpatialFeaturePlot(SLICE_3, features = "nCount_SCT", pt.size.factor = 2.5, stroke = 0.5) + theme(legend.position = "right")
p3_p4 <- plot_grid(plot3, plot4)


plot5 <- VlnPlot(SLICE_3, features = "nFeature_SCT", pt.size = 0.1) + NoLegend()
plot6 <- SpatialFeaturePlot(SLICE_3, features = "nFeature_SCT", pt.size.factor = 2.5, stroke = 0.5) + theme(legend.position = "right")
p5_p6 <- plot_grid(plot5, plot6)

p3_p4

p5_p6

ggsave(p3_p4, filename = "~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/nCountSCT.png", height = 10, width = 20, units = "in", dpi = 300)

ggsave(p5_p6, filename = "~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/nFeatureSCT.png", height = 10, width = 20, units = "in", dpi = 300)

p7_p8
p9_p10


ggsave(p7_p8, filename = "~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/clusters_nCountSCT.pdf", height = 7, width = 16, units = "in")
ggsave(p9_p10, filename = "~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/clusters_nFeaturesSCT.pdf", height = 7, width = 16, units = "in")

Highlight cells

SpatialDimPlot(SLICE_3, cells.highlight = CellsByIdentities(object = SLICE_3, idents = c(0, 1, 2, 3, 4, 5, 6)), facet.highlight = TRUE, ncol = 3, pt.size.factor = 2.5)

Calculate NPC and Neuron Scores

Voxhunt

pdf(file= "~/cell_lineage/Visium/V19S23-053/SLICE_3/plot_out/voxhunt.pdf")
p <- plot_map(vox_map)
adding dummy grobs
p
dev.off()
null device 
          1 
p

Feature Plots

SpatialFeaturePlot(SLICE_3, features = c("Tomato","OTX2", 'PAX6'), ncol = 3, pt.size.factor = 2.5)
SpatialFeaturePlot(SLICE_3, features = c("TBR1", "NEUROD6", "FOXG1"), ncol = 3, pt.size.factor = 2.5)

SpatialFeaturePlot(SLICE_3, features = c("HOXB2", "HOXB8", "HOXB5"), ncol = 3, pt.size.factor = 2.5)

SpatialFeaturePlot(SLICE_3, features = c("DCN", "TTR", "PRPH"), ncol = 3, pt.size.factor = 2.5)

SpatialFeaturePlot(SLICE_3, features = c("NEUROD1", "SOX10", "PMEL"), ncol = 3, pt.size.factor = 2.5)

SpatialFeaturePlot(SLICE_3, features = c("RSPO2", "RSPO3", "MEIS1"), ncol = 3, pt.size.factor = 2.5)

SLICE_3_coords <- SLICE_3@images$SLICE_3@coordinates
SLICE_3_anno <- cbind(SLICE_3@meta.data, SLICE_3_coords)
write.csv(SLICE_3_anno, file = "~/cell_lineage/Visium/V19S23-053/SLICE_3/data_out/SLICE_3_anno_w_coords.csv")
LS0tCnRpdGxlOiAiU0xJQ0VfMyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShkcGx5cikKbGlicmFyeShkZXZ0b29scykKYGBgCgpgYGB7cn0KU0xJQ0VfMyA8LSBMb2FkMTBYX1NwYXRpYWwoZGF0YS5kaXIgPSAiL2xvY2FsMS9EQVRBL3NlcXVlbmNpbmcvMjAyMDAyMjVfUDExNjhfQVNITEVZXzEwWF9WSVNJVU1fTGluZWFnZV9UcmFjaW5nX1Zpc2l1bV9kMTUvcHJvY2Vzc2VkL21hbnVhbF9hbGlnbm1lbnRzL1NMSUNFXzMvb3V0cy8iLCBzbGljZSA9ICJTTElDRV8zIiwgZmlsdGVyLm1hdHJpeCA9IFRSVUUpCmBgYAoKc2N0cmFuc2Zyb20gdG8gbm9ybWFsaXplIHRoZSBkYXRhIGFuZCBkZXRlY3QgaGlnaC12YXJpYW5jZSBmZWF0dXJlcwpgYGB7cn0KU0xJQ0VfMyA8LSBTQ1RyYW5zZm9ybShTTElDRV8zLCBhc3NheSA9ICJTcGF0aWFsIiwgdmVyYm9zZSA9IEZBTFNFKQpgYGAKCndyaXRlIHRhYmxlIHdpdGggcmF3IGRhdGEgY291bnRzCmBgYHtyfQp3cml0ZS50YWJsZShTTElDRV8zQGFzc2F5cyRTQ1RAY291bnRzLCBmaWxlID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvZGF0YV9vdXQvcmF3ZGF0YVNMSUNFM19TQ1QudHh0IiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIlx0IikKd3JpdGUudGFibGUoU0xJQ0VfM0Bhc3NheXMkU3BhdGlhbEBjb3VudHMsIGZpbGUgPSAifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9kYXRhX291dC9yYXdkYXRhU0xJQ0UzX1NwYXRpYWwudHh0IiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIlx0IikKClNDVF9jaWJzb3J0eF9pbnB1dCA8LSByZWFkLnRhYmxlKCJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL2RhdGFfb3V0L3Jhd2RhdGFTTElDRTNfU0NULnR4dCIsIHJvdy5uYW1lcyA9IE5VTEwsIHNlcCA9ICJcdCIpCmhlYWQoU0NUX2NpYnNvcnR4X2lucHV0KQpuYW1lcyhTQ1RfY2lic29ydHhfaW5wdXQpW25hbWVzKFNDVF9jaWJzb3J0eF9pbnB1dCkgPT0gInJvdy5uYW1lcyJdIDwtICJnZW5lcyIKaGVhZChTQ1RfY2lic29ydHhfaW5wdXQpCndyaXRlLnRhYmxlKFNDVF9jaWJzb3J0eF9pbnB1dCwgZmlsZSA9ICJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL2RhdGFfb3V0L1NDVF9jaWJzb3J0eF9pbnB1dF9TTElDRV8zLnR4dCIsIHF1b3RlID0gRkFMU0UsIHNlcCA9ICJcdCIsIHJvdy5uYW1lcz1GKQoKU3BhdGlhbF9jaWJzb3J0eF9pbnB1dCA8LSByZWFkLnRhYmxlKCJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL2RhdGFfb3V0L3Jhd2RhdGFTTElDRTNfU3BhdGlhbC50eHQiLCByb3cubmFtZXMgPSBOVUxMLCBzZXAgPSAiXHQiKQpoZWFkKFNwYXRpYWxfY2lic29ydHhfaW5wdXQpCm5hbWVzKFNwYXRpYWxfY2lic29ydHhfaW5wdXQpW25hbWVzKFNwYXRpYWxfY2lic29ydHhfaW5wdXQpID09ICJyb3cubmFtZXMiXSA8LSAiZ2VuZXMiCmhlYWQoU3BhdGlhbF9jaWJzb3J0eF9pbnB1dCkKd3JpdGUudGFibGUoU3BhdGlhbF9jaWJzb3J0eF9pbnB1dCwgZmlsZSA9ICJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL2RhdGFfb3V0L1NwYXRpYWxfY2lic29ydHhfaW5wdXRfU0xJQ0VfMy50eHQiLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiLCByb3cubmFtZXM9RikKYGBgCgppbnRlcmFjdGl2ZSAgcGxvdCB0byBpZGVudGlmeSBzcG90cyBub3QgY29ubmVjdGVkIHRvIHRpc3N1ZQpgYGB7cn0KSVNwYXRpYWxEaW1QbG90KFNMSUNFXzMsIGltYWdlID0gTlVMTCwgYWxwaGEgPSBjKDAuMywgMSkpCmBgYAoKRmlsdGVyIG91dCBzcG90cyB3aXRoIGxlc3MgdGhhbiAxMDAwIGZlYXR1cmUgYW5kIG5vdCBjb25uZWN0ZWQgdG8gdGlzc3VlCmBgYHtyfQojIGhpc3QoU0xJQ0VfMyRuRmVhdHVyZV9TcGF0aWFsKQojIGxvd19mZWF0dXJlX2N1dCA8LSAxMDAwCiMgV2hpY2hDZWxscyhTTElDRV8zLCBleHByZXNzaW9uID0gbkZlYXR1cmVfU3BhdGlhbCA8IGxvd19mZWF0dXJlX2N1dCkKIyBTcGF0aWFsRGltUGxvdChTTElDRV8zLCBjZWxscy5oaWdobGlnaHQgPSBXaGljaENlbGxzKFNMSUNFXzMsIGV4cHJlc3Npb24gPSBuRmVhdHVyZV9TcGF0aWFsIDwgbG93X2ZlYXR1cmVfY3V0KSkKIyBTcGF0aWFsRmVhdHVyZVBsb3QoU0xJQ0VfMywgZmVhdHVyZXMgPSAnbkZlYXR1cmVfU0NUJykKCiMgY2VsbHNfZHJvcCA8LSBXaGljaENlbGxzKFNMSUNFXzMsIGV4cHJlc3Npb24gPSBuRmVhdHVyZV9TcGF0aWFsIDwgbG93X2ZlYXR1cmVfY3V0KQojIGFsbF9jZWxsc190b2Ryb3AgPC0gcm93bmFtZXMoU0xJQ0VfM0BtZXRhLmRhdGEpW3doaWNoKHJvd25hbWVzKFNMSUNFXzNAbWV0YS5kYXRhKSAlaW4lIGMoY2VsbHNfZHJvcCkpXSAjYWxsIHNwb3RzIGFyZSB0b3VjaGluZyB0aXNzdWUgKHRoaXMgc2xpY2UgaXMgbWFudWFsbHkgdGlzc3VlIGFubm90YXRlZCB1cHN0cmVhbSBpbiBsb3VwZSBicm93c2VyKQojIAojIHBuZygifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC9EaW1wbG90X2NlbGxzdG9kcm9wLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKIyBTcGF0aWFsRGltUGxvdChTTElDRV8zLCBjZWxscy5oaWdobGlnaHQgPSBhbGxfY2VsbHNfdG9kcm9wLCBwdC5zaXplLmZhY3RvciA9IDIsIHN0cm9rZSA9IC41KQojIGRldi5vZmYoKQojIAojIGNlbGxzX3RvX2tlZXAgPC0gcm93bmFtZXMoU0xJQ0VfM0BtZXRhLmRhdGEpWyFyb3duYW1lcyhTTElDRV8zQG1ldGEuZGF0YSkgJWluJSBhbGxfY2VsbHNfdG9kcm9wXQojIAojIFNMSUNFXzNfc3ViIDwtIHN1YnNldChTTElDRV8zLCBjZWxscyA9IGNlbGxzX3RvX2tlZXApCmBgYAoKYGBge3J9ClNMSUNFXzMgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoU0xJQ0VfMywgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQpgYGAKCkRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiwgY2x1c3RlcmluZywgYW5kIHZpc3VhbGl6YXRpb24KYGBge3J9ClNMSUNFXzMgPC0gUnVuUENBKFNMSUNFXzMsIGFzc2F5ID0gIlNDVCIsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBTTElDRV8zKSwgdmVyYm9zZSA9IEZBTFNFKQpFbGJvd1Bsb3QoU0xJQ0VfMykKYGBgCgpGaW5kIApgYGB7cn0KZGltcyA9IDE6OQpTTElDRV8zIDwtIEZpbmROZWlnaGJvcnMoU0xJQ0VfMywgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSBkaW1zKQpgYGAKCkZpbmQgYmVzdCByZXNvbHV0aW9uIGZvciBjbHVzdGVyaW5nCmBgYHtyfQpTTElDRV8zIDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSBTTElDRV8zLCB2ZXJib3NlID0gVCwgcmVzb2x1dGlvbiA9IDAuMSkKU0xJQ0VfMyA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gU0xJQ0VfMywgdmVyYm9zZSA9IFQsIHJlc29sdXRpb24gPSAwLjMpClNMSUNFXzMgPC0gRmluZENsdXN0ZXJzKG9iamVjdCA9IFNMSUNFXzMsIHZlcmJvc2UgPSBULCByZXNvbHV0aW9uID0gMC41KQpTTElDRV8zIDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSBTTElDRV8zLCB2ZXJib3NlID0gVCwgcmVzb2x1dGlvbiA9IDAuNykKCiMgTWFrZSBwbG90IApjbHVzLnRyZWUub3V0IDwtIGNsdXN0cmVlKFNMSUNFXzMpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArIAogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICAgIHNjYWxlX2VkZ2VfY29sb3JfY29udGludW91cyhsb3cgPSAiZ3JleTgwIiwgaGlnaCA9ICJyZWQiKQojIFBsb3QgCnBuZygifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC9yZXNvbHV0aW9uX2NsdXN0cmVlLnBuZyIsIHdpZHRoID0gMTUsIGhlaWdodCA9IDEwLCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCkKY2x1cy50cmVlLm91dApkZXYub2ZmKCkKYGBgCgpGaW5kIGNsdXN0ZXJzIGFuZCBydW4gVU1BUApgYGB7cn0KcmVzIDwtIDAuNQpTTElDRV8zIDwtIEZpbmRDbHVzdGVycyhTTElDRV8zLCB2ZXJib3NlID0gRkFMU0UsIHJlc29sdXRpb24gPSByZXMpClNMSUNFXzMgPC0gUnVuVU1BUChTTElDRV8zLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IGRpbXMpCmBgYAoKcGxvdCBjbHVzdGVycwpgYGB7cn0KcDEgPC0gRGltUGxvdChTTElDRV8zLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgcHQuc2l6ZSA9IDIsICkKcDIgPC0gU3BhdGlhbERpbVBsb3QoU0xJQ0VfMywgbGFiZWwgPSBUUlVFLCBsYWJlbC5zaXplID0gMywgcHQuc2l6ZS5mYWN0b3IgPSAyLjUsIHN0cm9rZSA9IDAuNSkKcDFfMiA8LSBwbG90X2dyaWQocDEsIHAyKQoKcDFfMgpnZ3NhdmUocDFfMiwgZmlsZW5hbWUgPSAifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC9jbHVzdGVycy5wbmciLCBoZWlnaHQgPSAxMCwgd2lkdGggPSAyMCwgdW5pdHMgPSAiaW4iLCBkcGkgPSAzMDApCmBgYAoKcGxvdCBuZmVhdHVyZXMgYW5kIG5jb3VudHMKYGBge3J9CnBsb3QzIDwtIFZsblBsb3QoU0xJQ0VfMywgZmVhdHVyZXMgPSAibkNvdW50X1NDVCIsIHB0LnNpemUgPSAwLjEpICsgTm9MZWdlbmQoKQpwbG90NCA8LSBTcGF0aWFsRmVhdHVyZVBsb3QoU0xJQ0VfMywgZmVhdHVyZXMgPSAibkNvdW50X1NDVCIsIHB0LnNpemUuZmFjdG9yID0gMi41LCBzdHJva2UgPSAwLjUpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKcDNfcDQgPC0gcGxvdF9ncmlkKHBsb3QzLCBwbG90NCkKCgpwbG90NSA8LSBWbG5QbG90KFNMSUNFXzMsIGZlYXR1cmVzID0gIm5GZWF0dXJlX1NDVCIsIHB0LnNpemUgPSAwLjEpICsgTm9MZWdlbmQoKQpwbG90NiA8LSBTcGF0aWFsRmVhdHVyZVBsb3QoU0xJQ0VfMywgZmVhdHVyZXMgPSAibkZlYXR1cmVfU0NUIiwgcHQuc2l6ZS5mYWN0b3IgPSAyLjUsIHN0cm9rZSA9IDAuNSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpwNV9wNiA8LSBwbG90X2dyaWQocGxvdDUsIHBsb3Q2KQoKcDNfcDQKcDVfcDYKCmdnc2F2ZShwM19wNCwgZmlsZW5hbWUgPSAifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC9uQ291bnRTQ1QucG5nIiwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMjAsIHVuaXRzID0gImluIiwgZHBpID0gMzAwKQoKZ2dzYXZlKHA1X3A2LCBmaWxlbmFtZSA9ICJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL3Bsb3Rfb3V0L25GZWF0dXJlU0NULnBuZyIsIGhlaWdodCA9IDEwLCB3aWR0aCA9IDIwLCB1bml0cyA9ICJpbiIsIGRwaSA9IDMwMCkKYGBgCgpgYGB7cn0KcGxvdDcgPC0gVmxuUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9ICJuQ291bnRfU0NUIiwgcHQuc2l6ZSA9IDAuMSkgKyBOb0xlZ2VuZCgpCnBsb3Q4IDwtIFNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9ICJuQ291bnRfU0NUIiwgcHQuc2l6ZS5mYWN0b3IgPSAyLjUpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKcDdfcDggPC0gcGxvdF9ncmlkKHBsb3Q3LCBwbG90OCkKCgpwbG90OSA8LSBWbG5QbG90KFNMSUNFXzMsIGZlYXR1cmVzID0gIm5GZWF0dXJlX1NwYXRpYWwiLCBwdC5zaXplID0gMC4xKSArIE5vTGVnZW5kKCkKcGxvdDEwIDwtIFNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9ICJuRmVhdHVyZV9TcGF0aWFsIiwgcHQuc2l6ZS5mYWN0b3IgPSAyLjUpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKcDlfcDEwIDwtIHBsb3RfZ3JpZChwbG90OSwgcGxvdDEwKQoKcDdfcDgKcDlfcDEwCgpnZ3NhdmUocDdfcDgsIGZpbGVuYW1lID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvcGxvdF9vdXQvY2x1c3RlcnNfbkNvdW50U0NULnBkZiIsIGhlaWdodCA9IDcsIHdpZHRoID0gMTYsIHVuaXRzID0gImluIikKZ2dzYXZlKHA5X3AxMCwgZmlsZW5hbWUgPSAifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC9jbHVzdGVyc19uRmVhdHVyZXNTQ1QucGRmIiwgaGVpZ2h0ID0gNywgd2lkdGggPSAxNiwgdW5pdHMgPSAiaW4iKQpgYGAKCkhpZ2hsaWdodCBjZWxscwpgYGB7cn0KU3BhdGlhbERpbVBsb3QoU0xJQ0VfMywgY2VsbHMuaGlnaGxpZ2h0ID0gQ2VsbHNCeUlkZW50aXRpZXMob2JqZWN0ID0gU0xJQ0VfMywgaWRlbnRzID0gYygwLCAxLCAyLCAzLCA0LCA1LCA2KSksIGZhY2V0LmhpZ2hsaWdodCA9IFRSVUUsIG5jb2wgPSAzLCBwdC5zaXplLmZhY3RvciA9IDIuNSkKYGBgCgpDYWxjdWxhdGUgTlBDIGFuZCBOZXVyb24gU2NvcmVzCmBgYHtyfQpOUENfdGFiIDwtIHJlYWQudGFibGUoZmlsZSA9ICJ+L2NlbGxfbGluZWFnZS9wbG90X291dC9TTElDRTFfcGxvdHMvbGlzdC5OUENfc2lnbmF0dXJlLnR4dCIpCk5ldXJvbl90YWIgPC0gcmVhZC50YWJsZShmaWxlID0gIn4vY2VsbF9saW5lYWdlL3Bsb3Rfb3V0L1NMSUNFMV9wbG90cy9saXN0Lm5ldXJvbl9zaWduYXR1cmUudHh0IikKCk5QQ19zdWIgPC0gYXMuZGF0YS5mcmFtZShjb2xTdW1zKFNMSUNFXzNAYXNzYXlzJFNDVEBkYXRhW05QQ190YWIkVjEsIF0pKQpOZXVyb25fc3ViIDwtIGFzLmRhdGEuZnJhbWUoY29sU3VtcyhTTElDRV8zQGFzc2F5cyRTQ1RAZGF0YVtOZXVyb25fdGFiJFYxLCBdKSkKTlBDX05ldXJvbiA8LSBjYmluZChOUENfc3ViLCBOZXVyb25fc3ViKQpjb2xuYW1lcyhOUENfTmV1cm9uKSA8LSBjKCJOUENfU2NvcmUiLCAiTmV1cm9uX1Njb3JlIikKClNMSUNFXzNAbWV0YS5kYXRhIDwtIGNiaW5kKFNMSUNFXzNAbWV0YS5kYXRhLCBOUENfTmV1cm9uKQoKcG5nKGZpbGVuYW1lID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvcGxvdF9vdXQvbnBjX25ldXJvbl9zY29yZXMucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNywgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDApClNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9IGMoIk5QQ19TY29yZSIsIk5ldXJvbl9TY29yZSIpLCBwdC5zaXplLmZhY3RvciA9IDMsIHN0cm9rZSA9IDEpCmRldi5vZmYoKQpgYGAKCgpgYGB7cn0KZGVfbWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhTTElDRV8zKQpkZV9tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24oMjAsIGF2Z19sb2dGQykKd3JpdGUuY3N2KHggPSBkZV9tYXJrZXJzLCBmaWxlID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvZGF0YV9vdXQvZGVfbWFya2Vyc19TTElDRV8zLmNzdiIpCgpTcGF0aWFsRmVhdHVyZVBsb3Qob2JqZWN0ID0gU0xJQ0VfMywgZmVhdHVyZXMgPSByb3duYW1lcyhkZV9tYXJrZXJzKVsxOjNdLCBhbHBoYSA9IGMoMC4xLCAxKSwgbmNvbCA9IDMsIHB0LnNpemUuZmFjdG9yID0gMi41KQpgYGAKClZveGh1bnQKYGBge3J9CnRoZW1lX3NldCh0aGVtZV9idygpKQpsb2FkX2FiYV9kYXRhKCcvbGlua3MvZ3JvdXBzL3RyZXV0bGVpbi9QVUJMSUNfREFUQS90b29scy92b3hodW50X3BhY2thZ2UvJykKaGVhZChJZGVudHMoU0xJQ0VfMyksIDUpCmhlYWQoU0xJQ0VfM0BtZXRhLmRhdGEpCgpyZWdpb25hbF9tYXJrZXJzIDwtIHN0cnVjdHVyZV9tYXJrZXJzKCdFMTMnKSAlPiUKICAgIGdyb3VwX2J5KGdyb3VwKSAlPiUKICAgIHRvcF9uKDEwLCBhdWMpICU+JSAKICAgIHt1bmlxdWUoLiRnZW5lKX0KcmVnaW9uYWxfbWFya2VycwoKdm94X21hcCA8LSB2b3hlbF9tYXAoU0xJQ0VfMywgc3RhZ2UgPSAnRTEzJywgZ3JvdXBfbmFtZSA9ICdzZXVyYXRfY2x1c3RlcnMnLCBnZW5lc191c2UgPSByZWdpb25hbF9tYXJrZXJzKQp2b3hfbWFwCnBkZihmaWxlPSAifi9jZWxsX2xpbmVhZ2UvVmlzaXVtL1YxOVMyMy0wNTMvU0xJQ0VfMy9wbG90X291dC92b3hodW50LnBkZiIpCnAgPC0gcGxvdF9tYXAodm94X21hcCkKcApkZXYub2ZmKCkKcApgYGAKCkZlYXR1cmUgUGxvdHMKYGBge3J9CnBkZihmaWxlID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvcGxvdF9vdXQvZmVhdHVyZXBsb3RzLnBkZiIsIHdpZHRoID0gMTYsIGhlaWdodCA9IDcpClNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9IGMoIlRvbWF0byIsIk9UWDIiLCAnUEFYNicpLCBuY29sID0gMywgcHQuc2l6ZS5mYWN0b3IgPSAyLjUpClNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9IGMoIlRCUjEiLCAiTkVVUk9ENiIsICJGT1hHMSIpLCBuY29sID0gMywgcHQuc2l6ZS5mYWN0b3IgPSAyLjUpClNwYXRpYWxGZWF0dXJlUGxvdChTTElDRV8zLCBmZWF0dXJlcyA9IGMoIkhPWEIyIiwgIkhPWEI4IiwgIkhPWEI1IiksIG5jb2wgPSAzLCBwdC5zaXplLmZhY3RvciA9IDIuNSkKU3BhdGlhbEZlYXR1cmVQbG90KFNMSUNFXzMsIGZlYXR1cmVzID0gYygiRENOIiwgIlRUUiIsICJQUlBIIiksIG5jb2wgPSAzLCBwdC5zaXplLmZhY3RvciA9IDIuNSkKU3BhdGlhbEZlYXR1cmVQbG90KFNMSUNFXzMsIGZlYXR1cmVzID0gYygiTkVVUk9EMSIsICJTT1gxMCIsICJQTUVMIiksIG5jb2wgPSAzLCBwdC5zaXplLmZhY3RvciA9IDIuNSkKU3BhdGlhbEZlYXR1cmVQbG90KFNMSUNFXzMsIGZlYXR1cmVzID0gYygiUlNQTzIiLCAiUlNQTzMiLCAiTUVJUzEiKSwgbmNvbCA9IDMsIHB0LnNpemUuZmFjdG9yID0gMi41KQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0Kc2F2ZShTTElDRV8zLCBmaWxlID0gIn4vY2VsbF9saW5lYWdlL1Zpc2l1bS9WMTlTMjMtMDUzL1NMSUNFXzMvU0xJQ0VfMy5SRGF0YSIpCmBgYAoKYGBge3J9ClNMSUNFXzNfY29vcmRzIDwtIFNMSUNFXzNAaW1hZ2VzJFNMSUNFXzNAY29vcmRpbmF0ZXMKU0xJQ0VfM19hbm5vIDwtIGNiaW5kKFNMSUNFXzNAbWV0YS5kYXRhLCBTTElDRV8zX2Nvb3JkcykKd3JpdGUuY3N2KFNMSUNFXzNfYW5ubywgZmlsZSA9ICJ+L2NlbGxfbGluZWFnZS9WaXNpdW0vVjE5UzIzLTA1My9TTElDRV8zL2RhdGFfb3V0L1NMSUNFXzNfYW5ub193X2Nvb3Jkcy5jc3YiKQpgYGAK